﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using GPLib;
using MouseKeyboardActivityMonitor; //Global hook for monitoring

namespace GPGui
{
    public partial class GpDemoForm : Form
    {

        private readonly KeyboardHookListener _klistener;

        public GpDemoForm()
        {
            InitializeComponent();
            
            try
            {
                _klistener = new KeyboardHookListener( new MouseKeyboardActivityMonitor.WinApi.GlobalHooker() ) { Enabled = true };
                
            } catch ( Exception )
            {
                _klistener = null; //not available
                MessageBox.Show( this,
                                 @"Unable to start keylogger.  You can continue but you won't be able to see the results.",
                                 @"Keylogger initialization error", 
                                 MessageBoxButtons.OK, 
                                 MessageBoxIcon.Error );
            }

            if ( _klistener != null ) //set the keylogger keypress callback
                _klistener.KeyPress += GlobalHookKeyEvent;
        }

        private void GlobalHookKeyEvent( object sender, KeyPressEventArgs e )
        {
            KeyPressEventArgsExt kex = e as KeyPressEventArgsExt;
            richTextBox1.AppendText( kex.KeyChar.ToString() );
        }

        /// <summary>
        /// The callback from the GP will be one of 3 options:
        /// <br />
        /// <list type="number">
        ///     <item>String with length > 0: GP Form is closed.</item>
        ///     <item>String.Empty: GP Form is closed.  User either closed form or hit "Esc".</item>
        ///     <item>null: GP Form is open.  User lost focus of GP Form.</item>
        /// </list>
        /// </summary>
        /// <param name="s"></param>
        private void GpStringCallback( string s )
        {
            if ( s != null )
                textBox2.Text = s;
        }

        //This is for help in debugging but it makes for a great demonstration
        private void GpPositionCallback( List< int > positions )
        {

            foreach ( var i in positions )
            {
                richTextBox1.Select( i, 1 );
                richTextBox1.SelectionFont = new Font( richTextBox1.Font.FontFamily, richTextBox1.Font.Size, FontStyle.Bold );
                richTextBox1.SelectionColor = Color.Firebrick;
            }

        }

        private void Button1Click( object sender, EventArgs e )
        {
            richTextBox1.Clear();
            textBox2.Clear();

            char[] unmodifiedKeys = KeyboardLayout.GetUnmodifiedKeys;
            GpForm gpumpform = new GpForm( GpStringCallback, unmodifiedKeys, null, GpPositionCallback );

            /*
             * Adding shift keys is experimental.  The keylogger probably won't interpret the shifted keys unless you've 
             * physically pressed them down on your keyboard.  There's a small possibility that a character may appear as its shifted
             * counterpart, e.g., h -> H, 2 -> @ and vice-versa. 
             */
            //char[] shiftedKeys = KeyboardLayout.GetShiftedKeys;
            //GpForm gpumpform = new GpForm( GpStringCallback, unmodifiedKeys, shiftedKeys, GpPositionCallback ); //EXPERIMENTAL!

            /*
             * Do NOT use ShowDialog because attempting to click back onto the parent will not raise an OnLeave/OnDeactivate event and 
             * the characters from the garbage pump will be out of sync.
             */ 
            gpumpform.Show( this );

        }

        private void GpDemoFormFormClosing( object sender, FormClosingEventArgs e )
        {
            if ( _klistener != null )
                _klistener.Enabled = false;
        }

    }

}
